/*
 * Copyright (c) 2024 Shenzhen Kaihong Digital Industry Development Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "sle_connect_stub.h"
#include "sle_hilog.h"

namespace OHOS {
namespace NearLink {
namespace SleStandard {
SleConnectStub::SleConnectStub()
{
    memberFuncMap_[SleConnectInterfaceCode::SLE_REGISTER_CONNECT_CALLBACK] =
        &SleConnectStub::RegisterConnectCallbackInner;
    memberFuncMap_[SleConnectInterfaceCode::SLE_UNREGISTER_CONNECT_CALLBACK] =
        &SleConnectStub::UnregisterConnectCallbackInner;
    memberFuncMap_[SleConnectInterfaceCode::SLE_CONNECT] =
        &SleConnectStub::ConnectInner;
    memberFuncMap_[SleConnectInterfaceCode::SLE_DISCONNECT] =
        &SleConnectStub::DisconnectInner;
    memberFuncMap_[SleConnectInterfaceCode::SLE_GET_CONNECT_ID] =
        &SleConnectStub::GetConnectIdInner;
    memberFuncMap_[SleConnectInterfaceCode::SLE_GET_CONNECT_STATE] =
        &SleConnectStub::GetConnectStateInner;
    memberFuncMap_[SleConnectInterfaceCode::SLE_GET_CONNECT_DEVICE_LIST] =
        &SleConnectStub::GetConnectDeviceListInner;
    memberFuncMap_[SleConnectInterfaceCode::SLE_UPDATE_CONNECT_PARAM] =
        &SleConnectStub::UpdateConnectParamInner;
    memberFuncMap_[SleConnectInterfaceCode::SLE_UPDATE_ALL_CONNECT_PARAM] =
            &SleConnectStub::UpdateAllConnectParamInner;
    memberFuncMap_[SleConnectInterfaceCode::SLE_GET_RECOM_SEND_DATA_SIZE] =
            &SleConnectStub::GetRecomSendDataSizeInner;
    memberFuncMap_[SleConnectInterfaceCode::SLE_SEND_PAIR_REQUEST] =
        &SleConnectStub::SendPairRequestInner;
    memberFuncMap_[SleConnectInterfaceCode::SLE_REMOVE_PAIRED_DEVICE] =
        &SleConnectStub::RemovePairedDeviceInner;
    memberFuncMap_[SleConnectInterfaceCode::SLE_REMOVE_ALL_PAIRED_DEVICES] =
        &SleConnectStub::RemoveAllPairedDevicesInner;
    memberFuncMap_[SleConnectInterfaceCode::SLE_GET_PAIRED_DEVICES_NUMBER] =
        &SleConnectStub::GetPairedDevicesNumInner;
    memberFuncMap_[SleConnectInterfaceCode::SLE_GET_PAIRED_DEVICES] =
        &SleConnectStub::GetPairedDevicesInner;
    memberFuncMap_[SleConnectInterfaceCode::SLE_GET_PAIR_STATE] =
        &SleConnectStub::GetPairStateInner;
    memberFuncMap_[SleConnectInterfaceCode::SLE_READ_REMOTE_RSSI] =
        &SleConnectStub::ReadRemoteRssiInner;
}

SleConnectStub::~SleConnectStub(){}

int SleConnectStub::OnRemoteRequest(
    uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
{
    SLE_LOGD("cmd = %{public}d, flags= %{public}d", code, option.GetFlags());
    std::u16string descriptor = SleConnectStub::GetDescriptor();
    std::u16string remoteDescriptor = data.ReadInterfaceToken();
    SLE_ASSERT_AND_RETURN_RET_LOG(descriptor == remoteDescriptor, ERR_INVALID_STATE, "local descriptor is not equal to remote error!");

    auto itFunc = memberFuncMap_.find((SleConnectInterfaceCode)code);
    if (itFunc != memberFuncMap_.end()) {
        auto memberFunc = itFunc->second;
        if (memberFunc != nullptr) {
            return (this->*memberFunc)(data, reply);
        }
    }
    SLE_LOGW("default case, need check.");
    return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
}

int SleConnectStub::RegisterConnectCallbackInner(MessageParcel &data, MessageParcel &reply)
{
    SLE_LOGD("RegisterConnectCallbackInner In");
    sptr<IRemoteObject> remote = data.ReadRemoteObject();
    SLE_ASSERT_AND_RETURN_RET_LOG(remote, TRANSACTION_ERR, "read connect remote failed!");
    const sptr<ISleConnectCallback> callback = OHOS::iface_cast<ISleConnectCallback>(remote);
    SLE_ASSERT_AND_RETURN_RET_LOG(callback, TRANSACTION_ERR, "read connect callback failed!");

    int32_t result = RegisterConnectCallback(callback);
    SLE_ASSERT_AND_RETURN_RET_LOG(reply.WriteInt32(result), TRANSACTION_ERR, "write result failed!");
    return NO_ERROR;
}

int SleConnectStub::UnregisterConnectCallbackInner(MessageParcel &data, MessageParcel &reply)
{
    SLE_LOGD("UnregisterConnectCallbackInner In");
    sptr<IRemoteObject> remote = data.ReadRemoteObject();
    SLE_ASSERT_AND_RETURN_RET_LOG(remote, TRANSACTION_ERR, "read connect remote failed!");
    const sptr<ISleConnectCallback> callback = OHOS::iface_cast<ISleConnectCallback>(remote);
    SLE_ASSERT_AND_RETURN_RET_LOG(callback, TRANSACTION_ERR, "read connect callback failed!");

    int32_t result = UnregisterConnectCallback(callback);
    SLE_ASSERT_AND_RETURN_RET_LOG(reply.WriteInt32(result), TRANSACTION_ERR, "write result failed!");
    return NO_ERROR;
}

int SleConnectStub::ConnectInner(MessageParcel &data, MessageParcel &reply)
{
    SLE_LOGD("ConnectInner In");
    std::shared_ptr<SleAddress> address(data.ReadParcelable<SleAddress>());
    SLE_ASSERT_AND_RETURN_RET_LOG(address, TRANSACTION_ERR, "read address failed!");

    int32_t result = Connect(*address);
    SLE_ASSERT_AND_RETURN_RET_LOG(reply.WriteInt32(result), TRANSACTION_ERR, "write result failed!");
    return NO_ERROR;
}

int SleConnectStub::DisconnectInner(MessageParcel &data, MessageParcel &reply)
{
    SLE_LOGD("DisconnectInner In");
    std::shared_ptr<SleAddress> address(data.ReadParcelable<SleAddress>());
    SLE_ASSERT_AND_RETURN_RET_LOG(address, TRANSACTION_ERR, "read address failed!");

    int32_t result = Disconnect(*address);
    SLE_ASSERT_AND_RETURN_RET_LOG(reply.WriteInt32(result), TRANSACTION_ERR, "write result failed!");
    return NO_ERROR;
}

int SleConnectStub::GetConnectIdInner(MessageParcel &data, MessageParcel &reply)
{
    SLE_LOGD("GetConnectIdInner In");
    std::shared_ptr<SleAddress> address(data.ReadParcelable<SleAddress>());
    SLE_ASSERT_AND_RETURN_RET_LOG(address, TRANSACTION_ERR, "read address failed!");

    uint16_t connectId;
    int32_t result = GetConnectId(*address, connectId);
    SLE_ASSERT_AND_RETURN_RET_LOG(reply.WriteInt32(result), TRANSACTION_ERR, "write result failed!");
    SLE_ASSERT_AND_RETURN_RET_LOG(reply.WriteUint16(connectId), TRANSACTION_ERR, "write connect id back failed!");
    return NO_ERROR;
}

int SleConnectStub::GetConnectStateInner(MessageParcel &data, MessageParcel &reply)
{
    SLE_LOGD("GetConnectStateInner In");
    std::shared_ptr<SleAddress> address(data.ReadParcelable<SleAddress>());
    SLE_ASSERT_AND_RETURN_RET_LOG(address, TRANSACTION_ERR, "read address failed!");

    int32_t state;
    int32_t result = GetConnectState(*address, state);
    SLE_ASSERT_AND_RETURN_RET_LOG(reply.WriteInt32(result), TRANSACTION_ERR, "write result failed!");
    SLE_ASSERT_AND_RETURN_RET_LOG(reply.WriteInt32(state), TRANSACTION_ERR, "write connect state back failed!");
    return NO_ERROR;
}

int SleConnectStub::GetConnectDeviceListInner(MessageParcel &data, MessageParcel &reply)
{
    SLE_LOGD("GetConnectDeviceListInner In");
    uint16_t number;
    std::vector<SleConnectDevice> devices;
    int32_t result = GetConnectDeviceList(devices, number);
    SLE_ASSERT_AND_RETURN_RET_LOG(reply.WriteInt32(result), TRANSACTION_ERR, "write result failed!");
    SLE_ASSERT_AND_RETURN_RET_LOG(reply.WriteUint16(number), TRANSACTION_ERR, "write connect number failed!");
    for (auto device : devices) {
        SLE_ASSERT_AND_RETURN_RET_LOG(reply.WriteParcelable(&device), TRANSACTION_ERR, "write connect device failed!");
    }
    return NO_ERROR;
}

int SleConnectStub::UpdateConnectParamInner(MessageParcel &data, MessageParcel &reply)
{
    SLE_LOGD("UpdateConnectParamInner In");
    uint16_t connectId;
    SLE_ASSERT_AND_RETURN_RET_LOG(data.ReadUint16(connectId), TRANSACTION_ERR, "read connect id failed!");

    std::shared_ptr<SleConnectionParam> param(data.ReadParcelable<SleConnectionParam>());
    SLE_ASSERT_AND_RETURN_RET_LOG(param, TRANSACTION_ERR, "read connect param failed!");

    int32_t result = UpdateConnectParam(connectId, *param);
    SLE_ASSERT_AND_RETURN_RET_LOG(reply.WriteInt32(result), TRANSACTION_ERR, "write result failed!");
    return NO_ERROR;
}

int SleConnectStub::UpdateAllConnectParamInner(MessageParcel &data, MessageParcel &reply)
{
    SLE_LOGD("UpdateAllConnectParamInner In");
    uint16_t number = 0;
    std::vector<SleConnectDevice> successUpdateDevList;
    int32_t result = UpdateAllConnectParam(successUpdateDevList, number);
    SLE_ASSERT_AND_RETURN_RET_LOG(reply.WriteInt32(result), TRANSACTION_ERR, "write result failed!");
    SLE_ASSERT_AND_RETURN_RET_LOG(reply.WriteUint16(number), TRANSACTION_ERR, "write update number failed!");
    for (auto device : successUpdateDevList) {
        SLE_ASSERT_AND_RETURN_RET_LOG(reply.WriteParcelable(&device), TRANSACTION_ERR, "write connect device failed!");
    }
    return NO_ERROR;
}

int SleConnectStub::GetRecomSendDataSizeInner(MessageParcel &data, MessageParcel &reply)
{
    SLE_LOGD("GetRecomSendDataSizeInner In");
    uint16_t connectId;
    SLE_ASSERT_AND_RETURN_RET_LOG(data.ReadUint16(connectId), TRANSACTION_ERR, "read connect id failed!");
    uint32_t sendDataSize = 0;
    int32_t result = GetRecomSendDataSize(connectId, sendDataSize);
    SLE_ASSERT_AND_RETURN_RET_LOG(reply.WriteUint32(sendDataSize), TRANSACTION_ERR, "write recommend send data size failed!");
    SLE_ASSERT_AND_RETURN_RET_LOG(reply.WriteInt32(result), TRANSACTION_ERR, "write result failed!");
    return NO_ERROR;
}

int SleConnectStub::SendPairRequestInner(MessageParcel &data, MessageParcel &reply)
{
    SLE_LOGD("SendPairRequestInner In");
    std::shared_ptr<SleAddress> address(data.ReadParcelable<SleAddress>());
    SLE_ASSERT_AND_RETURN_RET_LOG(address, TRANSACTION_ERR, "read address failed!");

    int32_t result = SendPairRequest(*address);
    SLE_ASSERT_AND_RETURN_RET_LOG(reply.WriteInt32(result), TRANSACTION_ERR, "write result failed!");
    return NO_ERROR;
}

int SleConnectStub::RemovePairedDeviceInner(MessageParcel &data, MessageParcel &reply)
{
    SLE_LOGD("RemovePairedDeviceInner In");
    std::shared_ptr<SleAddress> address(data.ReadParcelable<SleAddress>());
    SLE_ASSERT_AND_RETURN_RET_LOG(address, TRANSACTION_ERR, "read address failed!");

    int32_t result = RemovePairedDevice(*address);
    SLE_ASSERT_AND_RETURN_RET_LOG(reply.WriteInt32(result), TRANSACTION_ERR, "write result failed!");
    return NO_ERROR;
}

int SleConnectStub::RemoveAllPairedDevicesInner(MessageParcel &data, MessageParcel &reply)
{
    SLE_LOGD("RemoveAllPairedDevicesInner In");
    int32_t result = RemoveAllPairedDevices();
    SLE_ASSERT_AND_RETURN_RET_LOG(reply.WriteInt32(result), TRANSACTION_ERR, "write result failed!");
    return NO_ERROR;
}

int SleConnectStub::GetPairedDevicesNumInner(MessageParcel &data, MessageParcel &reply)
{
    SLE_LOGD("GetPairedDevicesNumInner In");
    uint16_t number;
    int32_t result = GetPairedDevicesNum(number);
    SLE_ASSERT_AND_RETURN_RET_LOG(reply.WriteInt32(result), TRANSACTION_ERR, "write result failed!");
    SLE_ASSERT_AND_RETURN_RET_LOG(reply.WriteUint16(number), TRANSACTION_ERR, "write paired device number failed!");
    return NO_ERROR;
}

int SleConnectStub::GetPairedDevicesInner(MessageParcel &data, MessageParcel &reply)
{
    SLE_LOGD("GetPairedDevicesInner In");
    uint16_t number;
    std::vector<SleAddress> devices;
    int32_t result = GetPairedDevices(devices, number);
    SLE_ASSERT_AND_RETURN_RET_LOG(reply.WriteInt32(result), TRANSACTION_ERR, "write result failed!");
    SLE_ASSERT_AND_RETURN_RET_LOG(reply.WriteUint16(number), TRANSACTION_ERR, "write paired device number failed!");
    for (auto device : devices) {
        SLE_ASSERT_AND_RETURN_RET_LOG(reply.WriteParcelable(&device), TRANSACTION_ERR, "write paired device failed!");
    }
    return NO_ERROR;
}

int SleConnectStub::GetPairStateInner(MessageParcel &data, MessageParcel &reply)
{
    SLE_LOGD("GetPairStateInner In");
    std::shared_ptr<SleAddress> address(data.ReadParcelable<SleAddress>());
    SLE_ASSERT_AND_RETURN_RET_LOG(address, TRANSACTION_ERR, "read address failed!");

    uint8_t state;
    int32_t result = GetPairState(*address, state);
    SLE_ASSERT_AND_RETURN_RET_LOG(reply.WriteInt32(result), TRANSACTION_ERR, "write result failed!");
    SLE_ASSERT_AND_RETURN_RET_LOG(reply.WriteUint8(state), TRANSACTION_ERR, "write pair state back failed!");
    return NO_ERROR;
}

int SleConnectStub::ReadRemoteRssiInner(MessageParcel &data, MessageParcel &reply)
{
    SLE_LOGD("ReadRemoteRssiInner In");
    uint16_t connectId;
    SLE_ASSERT_AND_RETURN_RET_LOG(data.ReadUint16(connectId), TRANSACTION_ERR, "read connect id failed!");

    int32_t result = ReadRemoteRssi(connectId);
    SLE_ASSERT_AND_RETURN_RET_LOG(reply.WriteInt32(result), TRANSACTION_ERR, "write result failed!");
    return NO_ERROR;
}
} // SleStandard
} // NearLink
} // OHOS